// SCORELIGHT based on Arduino MEGA
// New version using OSC over ETHERNET
// April 30 2011, Alvaro Cassinelli

/* 
  NOTES:
  - IMPORTANT: The ethernet shield uses pin 10 to select the W5100 chip, and pin4 for the SD card, so it should be ok to use the same clock, miso, mosi pins for the SPI.. but the problem
    is that the Ethernet routines may use interruptions, and then interrupt the output to the mirror DAC!!! perhaps it would be better to set the SPI pins for the MCP4922 DAC on other pins. 
  - The OSC library used is a MODIFIED version of Recotana's, found here: http://www.makesomecode.com/wp-content/uploads/2010/11/OSCClass.zip
*/


//OSC related (could be in hardwareIO) ================================================
#include <SPI.h>
#include "Ethernet.h"
#include "OSCClass.h"
// (a) THIS ARDUINO IS THE SERVER:
byte serverMac[] = {0x90, 0xA2, 0xDA, 0x00, 0x20, 0xFF };
byte serverIp[]  = { 10, 0, 0, 2 };
int  serverPort  = 10000;
//  byte gateway[]   = { 192, 168, 0, 1 };
//  byte subnet[]    = { 255, 255, 255, 0 };

  // (b) SET THE ADDRESS OF THE CLIENT, i.e., Hirakawa's computer (is it needed? cannot we just reply?)
  byte destIp[]  = { 10,0,0,1}; // 
  int  destPort = 12000;
  
  
  // OSC message objects (for receveing and answering): 
OSCMessage recMes;
OSCMessage sendMes;
  
  // set the receving message that will be filled when receiving an osc packet: 
OSCClass osc(&recMes);
// =============================================================================

//============= LIBRARIES ====================================================
#include "hardwareIO.h" // rem: an extern SPI object is declared here, to be used both by the main program and the LivingSpot class
//#include "soundSpot.h"  // this is a derived class of livingSpot, with sending capabilities (for sound). 
#include "classSpotConfig.h"  


//#define SCHEDULERMODETIME 1200000//40000// 200000 // in milliseconds (REM: VERY LONG FOR SEKAI ICHI UKETAI JYUGYOU! (1200000=20 minutes...)
unsigned long SCHEDULERMODETIME = 5000;//modif Alexis time change for each mode
int schedulerMode;

/// ALWAYS instantiate 3 or 4 SPOTS (but they don't need to be "alive" at the same time)
/// midi and scheduler functions are using 4 spots
SpotConfiguration spotConfig; // note: I could have used a "new" constructor but I will statically assign NBSPOTS spots in the array (see constructor of SpotConfiguration)  
 
void setup(){
 
  // ===================  ETHERNET SETUP ===================
  // Important: il faut le faire AVANT d'utiliser le SPI (si on utilise la librarie SPI, car l'initialisation est dans le begin de Ethernet. Si on utilise une custom spi class, we need to call its init method!!!)
    // SET ETHERNET ADDRESS (IP and MAC):
     Ethernet.begin(serverMac ,serverIp);
    //Ethernet.begin(serverMac ,serverIp ,gateway ,subnet);
    
     //setting osc recieve server on specific PORT:
     osc.begin(serverPort);
   
     // set destination messages: 
      sendMes.setIp( destIp );
      sendMes.setPort( destPort );
      //sendMes.setTopAddress(topAddress); // topAddress="/ard"
      //sendMes.setSubAddress(subAddress[0]);
      
     //osc message buffer clear
     osc.flush();
     //==========================================================
     
        myMidi.init();// myMidi has been declared extern, so it is visible to functions in other files
        
       IO.init();  // set all the IO functions (PWM generation, SPI initialization, etc).
        // All other IO methods can be called AFTER we called the IO.init

  // for tests:
   // pinMode(31, OUTPUT); digitalWrite(31,HIGH); delay(200); digitalWrite(31, LOW); delay(200); digitalWrite(31,HIGH); delay(200); digitalWrite(31, LOW);   delay(200); digitalWrite(31,HIGH); 
 

  IO.setGreenPower(HIGH);
  IO.setRedPower_mW(MAX_RedLaserPower);
  
  // ===================  SERIAL SETUP on Serial port ===================
  // Setup serial communication with the computer:
  Serial.begin(115200);
  
 // SCHEDULER INITIALIZATION or all spots initialization but all "dead" for control through OSC:
  //schedulerInit();
  spotConfig.allSpotsInit();

  Serial.print("Arduino Server ready.");
}


// For tests angle:


/*
void loop(){
// mesure angle:
  // spotArray[0].measureAngle();

// measure limits:
        Spi.writeOutR(0);
        spotArray[0].drawMaxArea(1);
        digitalWrite(greenLaserPin, LOW);
        spotArray[0].drawMaxArea(10);
}
*/


void loop(){
  
   // PROCESSING INPUT COMMANDS:
   if ( osc.available() ) processOSC(); // this is basically to change the modes, etc. 
   if ( Serial.available() ) processSerial(); 
   // NOTE: we assume that MIDI is not sending commands, but could... (on Serial1)
   
   // AUTO SENDING MODES:
    
  
  // pin mode for MANUALLY changing modes: 
  if (digitalRead(pinSwitch)==LOW) {
    delay(200); // simple way to avoid switch bouncing
     spotConfig.configAge=SCHEDULERMODETIME; // so we enter the scheduler
   // Serial.println("button pressed");
  }
 
  // update dynamics (read new thresholds, change position but also radius, etc):
  spotConfig.update();
  
  // Send all the sound data for the config (this includes sending "packaged" data for all the spots, and perhaps also the config mode, but also send per-spot data if required):
  spotConfig.sendConfData(); 

  // update scheduler?
  // updateScheduler();
}






